import java.util.BitSet;

import javax.realtime.Clock;
import javax.realtime.PeriodicParameters;
import javax.realtime.PriorityParameters;
import javax.realtime.RealtimeThread;
import javax.realtime.RelativeTime;
import javax.realtime.ReleaseParameters;
import javax.realtime.SchedulingParameters;

import esrc.c9cf.schedulers.PartitionedPriorityScheduler;
import esrc.c9cf.schedulers.PartitionedRateMonotonic;


public class Test extends RealtimeThread {
	
	private static final int THREADS_PER_CPU = 5;
	private static final int CPUZ = 2;
	//private static final int DURATION = 3605000;			// 1 hour 5 sec
	private static final int DURATION = 65000;
	private static final int PERIOD_MS = 2000;	
	
	private static int THREADS = THREADS_PER_CPU * CPUZ;
	public boolean running = true;
	public int id;
	
	public Test(SchedulingParameters scheduling, ReleaseParameters release, BitSet affinity)
	{
		super(scheduling, release, affinity);
	}
	
	@Override
	public void run()
	{
		while(running)
		{
			//int z = 0;
			//for(int i = 0; i < Integer.MAX_VALUE; i++) for(int j = 0; j < 2; j++) z++;
			System.out.println("" + id + " RTThread, pid: " + getTID() + " time " + getReleaseParameters().getDeadline().getClock().getTime() + ", start " + super.getStartTime());
			waitForNextPeriod();
		}
	}
	
	public static void main(String[] args) {
		javax.realtime.Scheduler.setDefaultScheduler(PartitionedPriorityScheduler.instance());		// PFP
		//javax.realtime.Scheduler.setDefaultScheduler(PartitionedPriorityScheduler.instance());	// PRM

		Test[] tst = new Test[THREADS];
		
		int k = 0;
		for(int j = 0; j < CPUZ; j++)
		{
			for(int i = 0; i < THREADS_PER_CPU; i++)
			{
				BitSet affinity = new BitSet(Runtime.getRuntime().availableProcessors());
				affinity.set(j);
				
				// PFP
				
				tst[k] = new Test(
						new PriorityParameters(esrc.c9cf.schedulers.PartitionedPriorityScheduler.getNormPriority()+i),	// SchedulingParameters
						new PeriodicParameters(
								Clock.getRealtimeClock().getTime(),															// ReleaseParameters - start
								new RelativeTime(PERIOD_MS, 2000), new RelativeTime(2, 0),								// period, cost
								new RelativeTime(80, 0), null, null), 														// deadline, overrun, miss
								affinity);																									// Affinity
								
				// PRM
				/*
				tst[k] = new Test(
						PartitionedRateMonotonic.instance().getDefaultSchedulingParameters(),	// SchedulingParameters
						new PeriodicParameters(
								Clock.getRealtimeClock().getTime(),															// ReleaseParameters - start
								new RelativeTime(PERIOD_MS - k, 2000), new RelativeTime(2, 0),			// period, cost
								new RelativeTime(80, 0), null, null), 														// deadline, overrun, miss
								affinity);																									// Affinity
								*/
				tst[k].id = k;
				tst[k].setScheduler(esrc.c9cf.schedulers.PartitionedPriorityScheduler.instance());
				tst[k].start();
				k++;
			/*
			try {
				Thread.sleep(33);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}*/
		}
		}
		
		try {
			Thread.sleep(DURATION);
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
		for(int i = 0; i < THREADS; i++)
		{
			tst[i].running = false;
		}
		
		for(int i = 0; i < THREADS; i++)
		{
			try {
				tst[i].join();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
			
		
		System.out.println("End of program");
		
		/*
		Thread t = Thread.currentThread();
		t.suspend();
		System.out.println("Suspension of thread " + t.toString());
		
		System.out.println("End of program");
		*/
		
		/*
		long time1 = System.nanoTime();
		long time2 = System.nanoTime();
		//System.out.println(System.nanoTime());
		//System.out.println(System.nanoTime());
		System.out.println(time2 - time1);
		Test tst = new Test();
		tst.start();
		System.out.println("pid: " + NativeHelper.gettid());
		try {
			tst.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		*/
	}

}
